﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Management.Instrumentation;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;
using System.IO;
using wyDay.Controls;
using Framework.Forms;
using Framework.Logic.Server;
using Settings = Framework.Logic.Settings;
using Framework.Logic.Settings;

namespace UI
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }

        MCServer mcServer { get; set; }
        ConsoleChat consoleChat { get; set; }




        private void stop_Click(object sender, EventArgs e)
        {  
            this.Invoke((MethodInvoker)delegate
            {
                toolstripStatus.Text = "Stopping server";
                this.Refresh();
                if (mcServer != null && mcServer.outputReader != null)
                {
                    mcServer.Stop();
                }
                SetForm(false);
                lblStatusValue.Text = "Offline";
                toolstripStatus.Text = "Ready";
                btnCommandLine.Enabled = true;
                btnSplitChooseServer.Enabled = true;
            });
        }





        private void start_Click(object sender, EventArgs e)
        {
            EnablePowerOptions(false);
            string filePath = "";
            try
            {
                filePath = Framework.Logic.Settings.FileSystem.GetMCServerLocation(openFileDialog1);
            }
            catch (ArgumentException)
            {
                stop_Click(sender, e);
                return;
            }
            //lblLocation.Text = Path.GetFileName(filePath); //this label needs to move somewhere else! Needs a new ui

            toolstripStatus.Text = "Loading server";

            try
            {
                mcServer.NewErrorLine -= new EventHandler(mcServer_NewErrorLine);
                mcServer.NewErrorLine += new EventHandler(mcServer_NewErrorLine);
                mcServer.NewOutputLine -= new EventHandler(mcServer_NewOutputLine);
                mcServer.NewOutputLine += new EventHandler(mcServer_NewOutputLine);
                mcServer.Start(filePath);
                LoadServerProperties();
            }
            catch (InstanceNotFoundException ex)
            {
                mcServer.KillProcess();
                MessageBox.Show("Java runtime was not found", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
                Application.Exit();
            }
        }

        private void EnablePowerOptions(bool enable)
        {
            this.Invoke((MethodInvoker)delegate
            {
                    restartToolStripMenuItem.Enabled = enable;
                    stopToolStripMenuItem.Enabled = enable;
                    btnSplitChooseServer.Enabled = false;
                    btnCommandLine.Enabled = false;
                    reloadToolStripMenuItem.Enabled = enable;
                    if (!enable)
                    {
                        startToolStripMenuItem.Enabled = enable;
                    }
            });
        }

        void mcServer_NewOutputLine(object sender, EventArgs e)
        {
            if (sender.ToString().Contains("[INFO] Done"))
            {
                LoadServerProperties();
                mcServer.NewOutputLine -= new EventHandler(mcServer_NewOutputLine);
                toolstripStatus.Text = "Server loaded successfully.";
                SetForm(true);
                this.Invoke((MethodInvoker)delegate
                {
                    EnablePowerOptions(true);
                    lblStatusValue.Text = "Online";
                });
            }
            else if (sender.ToString().Contains("FAILED TO BIND TO PORT!"))
            {
                stop_Click(sender, e);
                mcServer.KillProcess();
                MessageBox.Show("The server failed to bind to the port. Is it already in use?", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void LoadServerProperties()
        {
            var filePath = Framework.Logic.Settings.FileSystem.GetMCServerLocation();
            if (string.IsNullOrWhiteSpace(filePath))
                return;

            ServerProperties props = new ServerProperties(Path.GetDirectoryName(filePath));
            this.Invoke((MethodInvoker)delegate
            {
                lblHostNameValue.Text = props.Hostname;
                lblPortValue.Text = props.Port;
                lblPlayersOnlineValue.Text = "0 of " + props.MaxPlayers;
            });
        }

        void mcServer_NewErrorLine(object sender, EventArgs e)
        {
            this.Invoke((MethodInvoker)delegate
            {
                stop_Click(sender, e);
                if (consoleChat != null)
                {
                    consoleChat.Close();
                    consoleChat.Dispose();
                }
                mcServer.KillProcess();
                MessageBox.Show(sender.ToString(), "An error occurred runing the minecraft server", MessageBoxButtons.OK, MessageBoxIcon.Stop);
            });
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            mcServer = new MCServer();
            SetForm(false);
            LoadServerProperties();
        }


        private void SetForm(bool Enable)
        {
            var ListOfButtons = new List<Button>();
            var ListOfTextBox = new List<TextBox>();
            var ListOfComboBox = new List<ComboBox>();
            var ListOfSplitButton = new List<SplitButton>();
            GetControlList<Button>(Controls, ListOfButtons);
            GetControlList<TextBox>(Controls, ListOfTextBox);
            GetControlList<ComboBox>(Controls, ListOfComboBox);
            GetControlList<SplitButton>(Controls, ListOfSplitButton);

            this.Invoke((MethodInvoker)delegate
            {
                foreach (var button in ListOfButtons)
                {
                    button.Enabled = (button.Text != "Command line arguments") ? Enable : !Enable;
                }

                foreach (var textbox in ListOfTextBox)
                {
                    textbox.Enabled = Enable;
                }

                foreach (var combo in ListOfComboBox)
                {
                    combo.Enabled = Enable;
                }

                foreach (var split in ListOfSplitButton)
                {
                    split.Enabled = (split.Text != "Select a server" ? Enable : !Enable);
                    if (split.Text == "Select a power option") split.Enabled = true;
                }

            });
        }


        private void GetControlList<T>(System.Windows.Forms.Control.ControlCollection controlCollection, List<T> resultCollection)
where T : Control
        {
            foreach (Control control in controlCollection)
            {
                if (control is T)
                    resultCollection.Add((T)control);

                if (control.HasChildren)
                    GetControlList(control.Controls, resultCollection);
            }
        }



        private void reload_Click(object sender, EventArgs e)
        {
            mcServer.Send("reload");
        }




        private void btnReset_Click(object sender, EventArgs e)
        {
            stop_Click(sender, e);
            Thread.Sleep(8000);
            start_Click(sender, e);
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (mcServer != null && mcServer.IsRunning)
            {
                if (MessageBox.Show("Are you sure you wish to exit? This will stop the minecraft server.", this.Text, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.No)
                {
                    e.Cancel = true;
                }
            }
        }

        private void btnLocation_Click(object sender, EventArgs e)
        {
            try
            {
                Framework.Logic.Settings.FileSystem.SetMCServerLocation(openFileDialog1);
            }
            catch
            {
                return;
            }
            //lblLocation.Text = Path.GetFileName(openFileDialog1.FileName); //this label needs to move somewhere else! Needs a new ui
        }

        private void btnDownload_Click(object sender, EventArgs e)
        {
            BukkitUpdate update = new BukkitUpdate();
            update.ShowDialog();
        }

        private void btnPopup_Click(object sender, EventArgs e)
        {
            if (consoleChat != null && !consoleChat.IsDisposed)
            {
                consoleChat.Close();
                consoleChat.Dispose();
            }
            consoleChat = new ConsoleChat(mcServer);
            consoleChat.Show();
        }

        private void btnSplitPowerOption_Click(object sender, EventArgs e)
        {
            mnuStripPowerOption.Show((Control)sender, 0, 23);
        }

        private void btnSplitChooseServer_Click(object sender, EventArgs e)
        {
            mnuStripSelectAServer.Show((Control)sender, 0, 23);
        }

        private void btnCommandLine_Click(object sender, EventArgs e)
        {
            CommandLineArguments commandLineForm = new CommandLineArguments();
            commandLineForm.ShowDialog();
        }

        private void mnuStripPowerOption_Opening(object sender, CancelEventArgs e)
        {
            if (mcServer == null || !mcServer.IsRunning)
            {
                stopToolStripMenuItem.Enabled = false;
                restartToolStripMenuItem.Enabled = false;
                reloadToolStripMenuItem.Enabled = false;
                startToolStripMenuItem.Enabled = true;
            }
        }
    }
}